﻿#include "qpicturebox.h"

QPictureBox::QPictureBox(QWidget *parent)
    : QOpenGLWidget(parent)
    , background(QColor(0, 0, 0, 255))
{
    data.resize(24);
    data = {
        -1.0f,  1.0f,  0.0f,  0.0f,
         1.0f,  1.0f,  1.0f,  0.0f,
         1.0f, -1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  0.0f,  0.0f,
        -1.0f, -1.0f,  0.0f,  1.0f,
         1.0f, -1.0f,  1.0f,  1.0f};
}

void QPictureBox::setImage(const QImage &image)
{
    image_data = image;
    repaint();
}

void QPictureBox::setImage(const QString &filename)
{
    image_data = QImage(filename);
    repaint();
}

void QPictureBox::setScaleType(QPictureBox::ScaleType x)
{
    image_Scale_Type = x;
}

void QPictureBox::setBackGround(QColor color)
{
    background = color;
}

void QPictureBox::initializeGL()
{
    initializeOpenGLFunctions();
    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    const char *vertexShaderSource =
        "#version 330 core\n"
        "layout(location=0)in vec2 aPos;\n"
        "layout(location=1)in vec2 aTexCoord;\n"
        "out vec2 TexCoord;\n"
        "uniform mat4 transform;\n"
        "void main()\n"
        "{\n"
        "gl_Position = transform * vec4(aPos,0.0f,1.0f);\n"
        "TexCoord = aTexCoord;\n"
        "}";
    vshader->compileSourceCode(vertexShaderSource);

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    const char *fsrc =
        "#version 330 core\n"
        "out vec4 FragColor;\n"
        "in vec2 TexCoord;\n"
        "uniform sampler2D ourTexture;\n"
        "void main()\n"
        "{FragColor = texture(ourTexture, TexCoord);}";
    fshader->compileSourceCode(fsrc);

    program.addShader(vshader);
    program.addShader(fshader);
    program.bindAttributeLocation("ourTexture", 0);
    program.bindAttributeLocation("transform", 1);
    program.link();
    program.bind();

    VBO.create();

    VBO.bind();
    VBO.allocate(data.data(), data.count() * sizeof(GLfloat));

    program.enableAttributeArray(0);
    program.setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(GLfloat));

    program.enableAttributeArray(1);
    program.setAttributeBuffer(1, GL_FLOAT, 2 * sizeof(GLfloat), 2, 4 * sizeof(GLfloat));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

}

void QPictureBox::paintGL()
{
    QMatrix4x4 trans_;
    float scale_im = (float)image_data.width() / (float)image_data.height();
    float scale_form = (float)width() / (float)height();
    switch (image_Scale_Type) {
    case fitXY:
        trans_.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
        break;
    case fitCenter:
        if(scale_im>scale_form)
            trans_.ortho(-1.0f, 1.0f, -scale_im / scale_form, scale_im / scale_form, -1.0f, 1.0f);
        else
            trans_.ortho(-scale_form / scale_im, scale_form / scale_im, -1.0f, 1.0f, -1.0f, 1.0f);
        break;
    case CenterCorp:
        if(scale_im>scale_form)
            trans_.ortho(-scale_form / scale_im, scale_form / scale_im, -1.0f, 1.0f, -1.0f, 1.0f);
        else
            trans_.ortho(-1.0f, 1.0f, -scale_im / scale_form, scale_im / scale_form, -1.0f, 1.0f);
        break;
        break;
    }
    program.setUniformValue("transform", trans_);
    if(!image_data.isNull()) {
        if (texture) {
            delete texture;
        }
        texture = new QOpenGLTexture(image_data);
        texture->bind();
    }
    glClearColor((GLfloat)background.red() / 255.0, (GLfloat)background.green() / 255.0,
                 (GLfloat)background.blue() / 255.0, (GLfloat)background.alpha() / 255.0);
    glDrawArrays(GL_TRIANGLES,0,data.count());

}
